import type { Mapless } from '..';
import type { IdHubType } from '../core/IdHub';
import IdHub from '../core/IdHub';
import { Manager } from '../core/manager';
import type { ManagerOptions, PolygonOptions } from '../index.d';

type PolygonIdHubType = IdHubType & {
  sourceId: string;
  layerId: string;
};

export default class PolygonManager extends Manager<PolygonIdHubType> {
  private polygons: Record<string, GeoJSON.GeoJSON> = {};

  constructor(mapless: Mapless, options?: ManagerOptions) {
    super(mapless, options, 'polygon');
    this.onInitialized();
  }

  override createIdHub(_idHub?: IdHubType) {
    const newHub = new IdHub({
      layers: {
        layerId: 'dzmap-polygon-layer',
      },
      sources: {
        sourceId: 'dzmap-polygon-source',
      },
    }) as PolygonIdHubType;
    super.createIdHub(newHub);
  }

  override initLayers() {
    if (!this.mapless) return;
    const sid = this.idHub?.sourceId;
    this.mapless.addEmptySource(sid);
    this.mapless.addLayer({
      id: this.idHub?.layerId,
      type: 'fill',
      source: sid,
      paint: {
        'fill-color': ['get', 'fillColor'],
        'fill-opacity': ['get', 'fillOpacity'],
        'fill-outline-color': this.mapless.isDark()
          ? 'rgba(250, 250, 250, 0.5)'
          : 'rgba(20, 20, 20, 0.5)',
      },
    });
  }

  override onStyleChanged = (tag: string) => {
    if (this.idHub?.layerId) {
      this.mapless?.map?.setPaintProperty(
        this.idHub?.layerId,
        'fill-outline-color',
        this.mapless.isDark(tag)
          ? 'rgba(250, 250, 250, 0.5)'
          : 'rgba(20, 20, 20, 0.5)',
        // ['coalesce', ['get', 'outlineColor'], tag === 'dz_dark' ? 'rgba(250, 250, 250, 0.5)' : 'rgba(20, 20, 20, 0.5)']
      );
    }
  };

  drawPolygon(id: string, options: PolygonOptions) {
    const {
      coordinates,
      fillColor = 'rgba(255,0,0,0.1)',
      fillOpacity = 1,
      outlineColor = 'rgba(250, 250, 250, 0.5)',
    } = options;
    const polygon = {
      type: 'Feature' as const,
      geometry: {
        type: 'Polygon' as const,
        coordinates: [coordinates],
      },
      properties: { id, fillColor, fillOpacity, outlineColor },
    };
    this.polygons[id] = polygon;
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features: Object.values(this.polygons) as GeoJSON.Feature<
        GeoJSON.Geometry,
        GeoJSON.GeoJsonProperties
      >[],
    });
  }

  removePolygon(id: string) {
    if (!this.polygons[id]) return;
    delete this.polygons[id];
    this.mapless?.setData(this.idHub?.sourceId, {
      type: 'FeatureCollection',
      features: Object.values(this.polygons) as GeoJSON.Feature<
        GeoJSON.Geometry,
        GeoJSON.GeoJsonProperties
      >[],
    });
  }

  removeAll() {
    this.mapless?.setEmptyData(this.idHub?.sourceId);
    this.polygons = {};
  }

  override destroy() {
    super.destroy();
    this.polygons = {};
  }
}

export const attachPolygon = (mapless: Mapless | undefined, name?: string) =>
  mapless?.use(PolygonManager, name);
export const getPolygon = (mapless: Mapless | undefined, name?: string) =>
  mapless?.get(PolygonManager, name);
export const detachPolygon = (mapless: Mapless | undefined, name?: string) =>
  mapless?.unuse(PolygonManager, name);
